package com.imcrl.effect
{
	import com.imcrl.effect.help.ControlePoint;
	import com.imcrl.effect.help.GenieTween;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.display.TriangleCulling;
	import flash.events.Event;
	import flash.filters.DropShadowFilter;
	import flash.geom.Point;
	
	import starling.animation.Tween;
	import starling.core.Starling;
	
	public class GenieEffect extends Sprite
	{
		private var cpTL : ControlePoint;
		private var cpTR : ControlePoint;
		private var cpBL : ControlePoint;
		private var cpBR : ControlePoint;
		private var top_arr : Array;
		private var left_arr : Array;
		private var right_arr : Array;
		private var bottem_arr : Array;
		public var bitmapData : BitmapData;
		private var indices : Vector.<int> = new Vector.<int>();
		private var rows : int = 15;
		private var cols : int = 15;
		private var rowWidth : Number;
		private var colsHeight : Number;
		public var holder : Sprite = new Sprite;
		
		private var dw:int;
		private var dh:int;
		private var hdw:int ;
		private var hdh:int
		public function GenieEffect(bmd:BitmapData)
		{
			dw=bmd.width;
			dh=bmd.height;
			
			rowWidth =dw / (cols - 1);
			colsHeight = dh / (rows - 1);
			
			hdw= dw>>1;
			hdh = dh>>1;
			prepTriangles();
			
			
			cpTL = new ControlePoint(0,0,hdw,hdh);
			cpTR = new ControlePoint(dw,0,-hdw,hdh);
			cpBL = new ControlePoint(0,dh,hdw,-hdh);
			cpBR = new ControlePoint(dw,dh,-hdw,-hdh);
			
			this.bitmapData=bmd;
			update()
		}
		
		private function update(event : Event = null) : void
		{
			
			var control1 : Point
			var control2 : Point
			
			
			// TOP LINE
			control1  = cpTL.add(cpTL.anchorH);
			control2  = cpTR.add(cpTR.anchorH);
			top_arr = getPointsArray(cpTL, control1, cpTR, control2, cols - 1)
			
			
			// BOTTEM LINE
			control1 =cpBL.add(cpBL.anchorH);
			control2 =cpBR.add(cpBR.anchorH);
			bottem_arr = getPointsArray(new Point(cpBL.x, cpBL.y), control1, new Point(cpBR.x, cpBR.y), control2, cols - 1)
			
			
			// LEFT LINE
			control1 =cpTL.add(cpTL.anchorV);
			control2 =cpBL.add(cpBL.anchorV);
			left_arr = getPointsArray(cpTL, control1, cpBL, control2, rows - 1)
			
			// RIGHT LINE
			control1 = cpTR.add(cpTR.anchorV);
			control2 = cpBR.add(cpBR.anchorV);
			right_arr = getPointsArray(cpTR, control1, cpBR, control2, rows - 1)
			
			var uvts : Vector.<Number> = new Vector.<Number>();
			var vertices : Vector.<Number> = new Vector.<Number>();
			var xPos : Number
			var yPos : Number
			
			vertices.length = 0;
			uvts.length = 0;
			
			for(var i : int = 0;i < rows; i++)
			{
				for(var j : int = 0;j < cols; j++)
				{
					
					var p : Point = getPoint(j, i)
					
					xPos = p.x
					yPos = p.y;
					
					
					vertices.push(xPos, yPos);
					uvts.push(j / (cols - 1), i / (rows - 1));
				}
			}
			
			
			graphics.clear();
			//graphics.lineStyle(1,0xFF0000);
			graphics.beginBitmapFill(bitmapData, null, false, true);
			graphics.drawTriangles(vertices, indices, uvts, TriangleCulling.NONE);
			graphics.endFill();
		}
		
		
		private function getPoint(xIndex : int, yIndex : int) : Point
		{
			var anchor1 : Point =left_arr[yIndex]
			var anchor2 : Point =  right_arr[yIndex]
			
			var inter : Number = ((rows - 1) - yIndex) / (rows - 1)
			
			var contLeft : Point = Point.interpolate(cpTL.anchorH, cpBL.anchorH, inter)
			var contRight : Point = Point.interpolate(cpTR.anchorH, cpBR.anchorH, inter)
			
			var control1 : Point = anchor1.add(contLeft);
			var control2 : Point = anchor2.add(contRight);
			
			var u : Number = xIndex * (1 / (rows - 1))
			
			var posX : Number = Math.pow(u, 3) * (anchor2.x + 3 * (control1.x - control2.x) - anchor1.x) + 3 * Math.pow(u, 2) * (anchor1.x - 2 * control1.x + control2.x) + 3 * u * (control1.x - anchor1.x) + anchor1.x;
			
			var posY : Number = Math.pow(u, 3) * (anchor2.y + 3 * (control1.y - control2.y) - anchor1.y) + 3 * Math.pow(u, 2) * (anchor1.y - 2 * control1.y + control2.y) + 3 * u * (control1.y - anchor1.y) + anchor1.y;
			
			return new Point(posX, posY);
		}
		
		private function getPointsArray(anchor1 : Point,control1 : Point , anchor2 : Point,control2 : Point,steps : int) : Array
		{
			var arr : Array = new Array()
			
			var posX : Number;
			var posY : Number;
			
			for (var u : Number = 0;u <= 1; u += 1 / steps) 
			{
				
				posX = Math.pow(u, 3) * (anchor2.x + 3 * (control1.x - control2.x) - anchor1.x) + 3 * Math.pow(u, 2) * (anchor1.x - 2 * control1.x + control2.x) + 3 * u * (control1.x - anchor1.x) + anchor1.x;
				
				posY = Math.pow(u, 3) * (anchor2.y + 3 * (control1.y - control2.y) - anchor1.y) + 3 * Math.pow(u, 2) * (anchor1.y - 2 * control1.y + control2.y) + 3 * u * (control1.y - anchor1.y) + anchor1.y;
				
				arr.push(new Point(posX, posY))
			}
			
			return arr
		}
		
		public function prepTriangles() : void
		{
			for(var i : int = 0;i < rows; i++)
			{
				for(var j : int = 0;j < cols; j++)
				{
					if(i < rows - 1 && j < cols - 1)
					{
						indices.push(i * cols + j, i * cols + j + 1, (i + 1) * cols + j);
						
						indices.push(i * cols + j + 1, (i + 1) * cols + j + 1, (i + 1) * cols + j);
					}
				}
			}
		}
		
		
		public function hide(x:int,y:int):void{
			
			var tween:GenieTween=new GenieTween(this);
			tween.cpTL=cpTL;
			tween.cpTR =cpTR;
			tween.cpBL =cpBL;
			tween.cpBR =cpBR;
			tween.dh=dh;
			tween.dw=dw;
			tween.hdh=hdh;
			tween.hdw=hdw;
		
			tween.onUpdate=update;
			tween.moveTo(x,y);
		}
	}
}
